home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / prg_casm / snpd9611.zip / BITOPS.HOW < prev    next >
Text File  |  1996-11-24  |  3KB  |  87 lines

  1. +++Date last modified: 30-Aug-1996
  2.  
  3. /*
  4. **  Bit set, clear, and test operations
  5. **
  6. **  public domain snippet by Bob Stout
  7. */
  8.  
  9. typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;
  10.  
  11. #define BOOL(x) (!(!(x)))
  12.  
  13. #define BitSet(arg,posn) ((arg) | (1L << (posn)))
  14. #define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
  15. #define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
  16. #define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
  17.  
  18.   OK, let's analyze things...
  19.  
  20.   The common expression in all of these that you seem to be having problems
  21. with is "(1L << (posn))". All this does is create a mask with a single bit on
  22. and which will work with any integer type. The "posn" argument specifies the
  23. position where you want the bit. If posn==0, then this expression will
  24. evaluate to:
  25.  
  26.         0000 0000 0000 0000 0000 0000 0000 0001 binary.
  27.  
  28. If posn==8, it will evaluate to
  29.  
  30.         0000 0000 0000 0000 0000 0001 0000 0000 binary.
  31.  
  32.   In other words, it simply creates a field of 0's with a 1 at the specified
  33. position. The only tricky part is in the BitClr() macro where we need to set
  34. a single 0 bit in a field of 1's. This is accomplished by using the 1's
  35. complement of the same expression as denoted by the tilde (~) operator.
  36.  
  37.   Once the mask is created it's applied to the arugment just as you suggest,
  38. by use of the bitwise and (&), or (|), and xor (^) operators. Since the mask
  39. is of type long, the macros will work just as well on char's, short's, int's,
  40. or long's.
  41.  
  42.   The bottom line is that this is a general solution to an entire class of
  43. problems. It is, of course, possible and even appropriate to rewrite the
  44. equivalent of any of these macros with explicit mask values every time you
  45. need one, but why do it? Remember, the macro substitution occurs in the
  46. preprocessor and so the generated code will reflect the fact that the values
  47. are considered constant by the compiler - i.e. it's just as efficient to use
  48. the generalized macros as to "reinvent the wheel" everytime you need to do
  49. bit manipulation. 
  50.  
  51.   Unconvinced? Here's some test code - I used Watcom C with full optimization
  52. and without using _cdecl so the resulting disassembly would be as clean as
  53. possible:
  54.  
  55. ----[ TEST.C ]----------------------------------------------------------------
  56.  
  57. #define BOOL(x) (!(!(x)))
  58.  
  59. #define BitSet(arg,posn) ((arg) | (1L << (posn)))
  60. #define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
  61. #define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
  62. #define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
  63.  
  64. int bitmanip(int word)
  65. {
  66.       word = BitSet(word, 2);
  67.       word = BitSet(word, 7);
  68.       word = BitClr(word, 3);
  69.       word = BitFlp(word, 9);
  70.       return word;
  71. }
  72.  
  73. ----[ TEST.OUT (disassembled) ]-----------------------------------------------
  74.  
  75. Module: C:\BINK\tst.c
  76. Group: 'DGROUP' CONST,CONST2,_DATA,_BSS
  77.  
  78. Segment: _TEXT  BYTE   00000008 bytes  
  79.  0000  0c 84             bitmanip_       or      al,84H
  80.  0002  80 f4 02                          xor     ah,02H
  81.  0005  24 f7                             and     al,0f7H
  82.  0007  c3                                ret     
  83.  
  84. No disassembly errors
  85.  
  86. ----[ finis ]----------------------------------------------------------------- 
  87.